<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <div>
      <p>
        <span>{{name.firstname}}</span>
      </p>
    </div>
    <p>{{name.secondname}}</p>
  </div>
  <script>
    /*
    1. 获取模板引擎
    2. 递归遍历，将模板中的{{}}替换成data中的数据（保留模板，深度数据查找
    3. 将模板替换到页面的根元素中
    */
   let rkuohao = /\{\{(.+?)\}\}/g;

   function getValueByKey(obj,path) {
    let paths = path.split('.');
    let res = obj;
    let prop;
    while(prop = paths.shift()) {
      res = res[prop]
    }
    return res
   }

   function compiler(template, data) {
     let childNodes = template.childNodes;
     for(let i =0;i<childNodes.length;i++) {
       let type = childNodes[i].nodeType;
       if(type === 3) { // 文本
        let txt = childNodes[i].nodeValue;
        txt = txt.replace(rkuohao, function(_, g) {
          let key = g.trim();
          let value = getValueByKey(data, key)
          return value
        })
        // 注意txt现在和dom元素是没有关系的
        childNodes[i].nodeValue = txt;
       } else if(type === 1) {
         compiler(childNodes[i], data)
       }
     }
   }

   function YCVue(options) {
    this._el = options.el;
    this._data = options.data;
    // 准备工作（准备模板）
    this._tmpNode = document.querySelector(this._el);
    this._parent = this._tmpNode.parentNode;
    this.render()
   }
   YCVue.prototype.render = function() {
    this.compiler()
   }
   YCVue.prototype.compiler = function() {
    let tmp = this._tmpNode.cloneNode(true)
    compiler(tmp, this._data)
    this.update(tmp)
   }

   YCVue.prototype.update = function(tmp) {
    this._parent.replaceChild(tmp, document.querySelector('#root'))
   }

   let app = new YCVue({
     el: '#root',
     data: {
       name: {
         firstname: 'zhang',
         secondname: '三'
       }
     }
   })
  </script>
</body>
</html>